package com.umeox.watch.moto.dataservice.stub;

import android.os.IBinder;
import android.os.RemoteException;
import android.util.SparseArray;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.protobuf.InvalidProtocolBufferException;
import com.umeox.moto.common.log.Logger;
import com.umeox.moto.mqtt.base.AError;
import com.umeox.moto.mqtt.base.ARequest;
import com.umeox.moto.mqtt.base.AResponse;
import com.umeox.watch.location.proto.LocationProto;
import com.umeox.watch.moto.apiclient.model.AlbumDTO;
import com.umeox.watch.moto.apiclient.model.ChantsCountDTO;
import com.umeox.watch.moto.apiclient.model.ChantsCounterDTO;
import com.umeox.watch.moto.apiclient.model.FileSignDTO;
import com.umeox.watch.moto.apiclient.model.RecordDTO;
import com.umeox.watch.moto.apiclient.model.SubmitTaskRecordDTO;
import com.umeox.watch.moto.dataservice.BuildConfig;
import com.umeox.watch.moto.dataservice.DataProvider;
import com.umeox.watch.moto.dataservice.base.BaseApp;
import com.umeox.watch.moto.dataservice.constants.MqttConstants;
import com.umeox.watch.moto.dataservice.interfaces.IPullApiClient;
import com.umeox.watch.moto.dataservice.mqtt.PayloadMessage;
import com.umeox.watch.moto.dataservice.mqtt.bean.FileSignBody;
import com.umeox.watch.moto.dataservice.mqtt.impl.MqttServiceDelegate;
import com.umeox.watch.moto.dataservice.mqtt.interfaces.IPublishListener;
import com.umeox.watch.moto.dataservice.mqtt.request.EventRequest;
import com.umeox.watch.moto.dataservice.services.ApiService;
import com.umeox.watch.moto.dataservice.services.LocationService;

import net.vidageek.mirror.dsl.Mirror;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

public class PullApiClientStub extends android.os.Binder implements IPullApiClient {

    public PullApiClientStub() {
        this.attachInterface(this, DESCRIPTOR);
    }

    public static void registerBinder() {
        try {
            new Mirror().on("android.os.ServiceManager").invoke().method("addService").withArgs(BuildConfig.pullApiBinderName, new PullApiClientStub());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public IBinder asBinder() {
        return this;
    }

    @Override
    public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws RemoteException {
        String descriptor = DESCRIPTOR;
        switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(descriptor);
                return true;
            }
            case TRANSACTION_UPLOAD_FILE: {
                data.enforceInterface(descriptor);
                String objectName = data.readString();
                String filePath = data.readString();
                String result = this.uploadFile(objectName, filePath);
                reply.writeNoException();
                reply.writeString(result);
                return true;
            }
            case TRANSACTION_UPLOAD_STEP: {
                data.enforceInterface(descriptor);
                this.uploadStep(data.readInt());
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_UPLOAD_LOCATION: {
                data.enforceInterface(descriptor);
                boolean result = this.uploadLocation(data.readInt(), data.createByteArray());
                reply.writeNoException();
                reply.writeByte((byte) (result ? 1 : 0));
                return true;
            }
            case TRANSACTION_UPLOAD_SOS_LOCATION: {
                data.enforceInterface(descriptor);
                String result = this.uploadSosLocation(data.createByteArray());
                reply.writeNoException();
                reply.writeString(result);
                return true;
            }
            case TRANSACTION_UPLOAD_SOS: {
                data.enforceInterface(descriptor);
                long sosId = data.readInt();
                String fileId = data.readString();
                boolean result = this.uploadSos(sosId, fileId);
                reply.writeNoException();
                reply.writeByte((byte) (result ? 1 : 0));
                return true;
            }
            case TRANSACTION_UPLOAD_SOS_FILE: {
                data.enforceInterface(descriptor);
                String filePath = data.readString();
                String result = this.uploadSOSFile(filePath);
                reply.writeNoException();
                reply.writeString(result);
                return true;
            }
            case TRANSACTION_UPLOAD_ALUM_FILE: {
                data.enforceInterface(descriptor);
                String filePath = data.readString();
                String result = this.uploadAlumFile(filePath);
                reply.writeNoException();
                reply.writeString(result);
                return true;
            }
            case TRANSACTION_UPLOAD_SOSR: {
                data.enforceInterface(descriptor);
                String sosEid = data.readString();
                String fileUrl = data.readString();
                boolean result = this.uploadSOSR(sosEid, fileUrl);
                reply.writeNoException();
                reply.writeByte((byte) (result ? 1 : 0));
                return true;
            }
            case TRANSACTION_UPLOAD_ALB: {
                data.enforceInterface(descriptor);
                SparseArray<AlbumDTO> fileUrls = data.readSparseArray(AlbumDTO.class.getClassLoader());
                this.uploadALB(fileUrls);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_REQUEST_SOS2: {
                data.enforceInterface(descriptor);
                String sosEid = data.readString();
                this.requestSOS2Location(sosEid);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_UPLOAD_HEART_RATE: {
                data.enforceInterface(descriptor);
                String hrCode = data.readString();
                long startTime = data.readLong();
                long endTime = data.readLong();
                int avgValue = data.readInt();
                int minValue = data.readInt();
                int maxValue = data.readInt();
                this.uploadHeartRate(hrCode, startTime, endTime, avgValue, minValue, maxValue);
                reply.writeNoException();
                return true;
            }
            case TRANSACTION_UPLOAD_CHALLENGE_RECORD: {
                data.enforceInterface(descriptor);
                int sportChallengeId = data.readInt();
                int sportType = data.readInt();
                String startTime = data.readString();
                String endTime = data.readString();
                int totalTime = data.readInt();
                int rewardValue = data.readInt();
                boolean result = this.uploadChallengeRecord(sportChallengeId, sportType, startTime, endTime, totalTime, rewardValue);
                reply.writeNoException();
                reply.writeByte((byte) (result ? 1 : 0));
                return true;
            }
            case TRANSACTION_UPLOAD_QURAN_CHALLENGE_RECORD: {
                data.enforceInterface(descriptor);
                int quranLearnId = data.readInt();
                int chapterIndex = data.readInt();
                String finishTime = data.readString();
                int duration = data.readInt();
                int rewardValue = data.readInt();
                boolean result = this.uploadQuranChallengeRecord(quranLearnId, chapterIndex, finishTime, duration, rewardValue);
                reply.writeNoException();
                reply.writeByte((byte) (result ? 1 : 0));
                return true;
            }
            case TRANSACTION_UPLOAD_CHANTS_COUNT: {
                data.enforceInterface(descriptor);
                List<ChantsCountDTO> chantsCountDTOList = new ArrayList<>();
                data.readTypedList(chantsCountDTOList, ChantsCountDTO.CREATOR);
                boolean result = this.uploadChants(chantsCountDTOList);
                reply.writeNoException();
                reply.writeByte((byte) (result ? 1 : 0));
                return true;
            }
            case TRANSACTION_UPLOAD_FILE_BY_FILE_TYPE: {
                data.enforceInterface(descriptor);
                String filePath = data.readString();
                int fileType = data.readInt();
                String result = this.uploadFileByFileType(filePath, fileType);
                reply.writeNoException();
                reply.writeString(result);
                return true;
            }
            case TRANSACTION_SUBMIT_TASK_RECORD: {
                data.enforceInterface(descriptor);
                String requestId = data.readString();
                List<SubmitTaskRecordDTO> list = new ArrayList<>();
                data.readTypedList(list, SubmitTaskRecordDTO.CREATOR);
                this.submitTaskRecord(requestId, list);
                reply.writeNoException();
                return true;
            }
            default: {
                return super.onTransact(code, data, reply, flags);
            }
        }
    }

    @Override
    public String uploadFile(String objectName, String filePath) {
        return ApiService.uploadFile(filePath);
    }

    @Override
    public String uploadSOSFile(String filePath) {
        //getFileSign
        JSONObject jsonObject = new JSONObject();
        FileSignBody fileSignBody = FileSignBody.Builder.aFileSignBody()
                .setHolderId(DataProvider.getHolderId())
                .setServiceType(1)
                .setFileType(13) //13：SOS录音
                .build();
        JSONObject paramsJsonObject = (JSONObject) JSONObject.toJSON(fileSignBody);
        jsonObject.put("method", MqttConstants.ClientRpcMethod.GET_FILE_SIGN);
        jsonObject.put("params", paramsJsonObject);
        final AtomicReference<FileSignDTO> result = new AtomicReference<>(null);
        CountDownLatch downLatch = new CountDownLatch(1);
        MqttServiceDelegate.getFileSign(jsonObject, new IPublishListener() {

            @Override
            public void onSuccess(ARequest request, AResponse response) {
                String data = response.data.toString();
                Logger.i("getFileSign成功->" + data);
                JSONObject jsonObject = JSONObject.parseObject(data);
                if (jsonObject.containsKey("result")) {
                    FileSignDTO fileSignDTO = jsonObject.getObject("result", FileSignDTO.class);
                    result.set(fileSignDTO);
                } else {
                    int errCode = jsonObject.getIntValue(PayloadMessage.ERR_CODE);
                    String errMsg = jsonObject.getString(PayloadMessage.ERR_MSG);
                    Logger.e("ApiService", "ERR_CODE->" + errCode + ",ERR_MSG->" + errMsg);
                }
                downLatch.countDown();
            }

            @Override
            public void onFailure(ARequest request, Object message, AError error) {
                Logger.i("getFileSign失败：" + error.getMsg());
                downLatch.countDown();
            }
        });
        if (downLatch.getCount() > 0) {
            try {
                downLatch.await(15, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        if (result.get() != null) {
            return ApiService.uploadFile(result.get(), filePath);
        }
        return null;
    }

    @Override
    public void uploadStep(int stepCount) {
        ApiService.uploadStepInfo(stepCount);
    }

    @Override
    public boolean uploadSOSR(String sosEid, String fileUrl) {
        RecordDTO recordDTO = RecordDTO.Builder.aRecordDTO()
                .setSosEventId(sosEid)
                .setHolderId(DataProvider.getHolderId())
                .setFile(fileUrl)
                .build();
        final AtomicBoolean result = new AtomicBoolean(false);
        CountDownLatch downLatch = new CountDownLatch(1);
        MqttServiceDelegate.sendEvent(MqttConstants.Event.SOSR, JSONObject.toJSON(recordDTO), new IPublishListener() {
            @Override
            public void onSuccess(ARequest request, AResponse response) {
                Logger.i("上报SOSR事件成功");
                result.set(true);
                downLatch.countDown();
            }

            @Override
            public void onFailure(ARequest request, Object message, AError error) {
                Logger.i("上报SOSR事件失败，原因：" + error.getMsg());
            }
        });

        if (downLatch.getCount() > 0) {
            try {
                downLatch.await(10, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        return result.get();
    }

    @Override
    public boolean uploadLocation(int locReason, byte[] data) throws RemoteException {
        LocationProto.LocationDetail detail = null;
        try {
            detail = LocationProto.LocationDetail.parseFrom(data);
            if (detail == null) {
                return false;
            }
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }

        final AtomicBoolean result = new AtomicBoolean(false);
        ApiService.uploadLocationInfo(locReason, detail, new IPublishListener() {

            @Override
            public void onSuccess(ARequest request, AResponse response) {
                Logger.i("上传位置成功");
                result.set(true);
            }

            @Override
            public void onFailure(ARequest request, Object message, AError error) {
                Logger.i("上传位置失败");
            }
        });
        return result.get();
    }

    @Override
    public String uploadSosLocation(byte[] data) throws RemoteException {
        LocationProto.LocationDetail detail = null;
        try {
            detail = LocationProto.LocationDetail.parseFrom(data);
            if (detail == null) {
                return null;
            }
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }
        final AtomicReference<String> result = new AtomicReference<>();
        CountDownLatch downLatch = new CountDownLatch(1);
        ApiService.uploadLocationInfo(LocationProto.LocReason.SOS_LOCATION_VALUE, detail, new IPublishListener() {

            @Override
            public void onSuccess(ARequest request, AResponse response) {
                Logger.i("sos位置发送成功");
                EventRequest eventRequest = (EventRequest) request;
                JSONObject jsonObject = JSONObject.parseObject((String) eventRequest.payloadObj);
                JSONObject baseLocation = jsonObject.getJSONObject("params");
                result.set(baseLocation.getString("eventId"));
                downLatch.countDown();
            }

            @Override
            public void onFailure(ARequest request, Object message, AError error) {
                Logger.i("sos位置发送失败" + error.getMsg());
                downLatch.countDown();
            }
        });
        if (downLatch.getCount() > 0) {
            try {
                downLatch.await(15, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return result.get();
    }

    @Override
    public boolean uploadSos(long sosId, String fileId) {
        final AtomicBoolean result = new AtomicBoolean(false);
        CountDownLatch downLatch = new CountDownLatch(1);
        ApiService.uploadSos(BaseApp.getInstance().deviceId, sosId, fileId, System.currentTimeMillis(), (success, object) -> {
            result.set(success);
            downLatch.countDown();
        });
        if (downLatch.getCount() > 0) {
            try {
                downLatch.await(30, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return result.get();
    }

    @Override
    public void requestSOS2Location(String eid) {
        LocationService.sos2Location(BaseApp.getInstance().getApplicationContext(), eid);
    }

    @Override
    public void uploadHeartRate(String code, long startTime, long endTime, int avgValue, int minValue, int maxValue) throws RemoteException {
        ApiService.uploadHeartRate(code, startTime, endTime, avgValue, minValue, maxValue);
    }

    @Override
    public String uploadAlumFile(String filePath) {
        //getFileSign
        JSONObject jsonObject = new JSONObject();
        FileSignBody fileSignBody = FileSignBody.Builder.aFileSignBody()
                .setHolderId(DataProvider.getHolderId())
                .setServiceType(1)
                .setFileType(12) //12：分享相册
                .build();
        JSONObject paramsJsonObject = (JSONObject) JSONObject.toJSON(fileSignBody);
        jsonObject.put("method", MqttConstants.ClientRpcMethod.GET_FILE_SIGN);
        jsonObject.put("params", paramsJsonObject);
        final AtomicReference<FileSignDTO> result = new AtomicReference<>(null);
        CountDownLatch downLatch = new CountDownLatch(1);
        MqttServiceDelegate.getFileSign(jsonObject, new IPublishListener() {

            @Override
            public void onSuccess(ARequest request, AResponse response) {
                String data = response.data.toString();
                Logger.i("getFileSign成功->" + data);
                JSONObject jsonObject = JSONObject.parseObject(data);
                if (jsonObject.containsKey("result")) {
                    FileSignDTO fileSignDTO = jsonObject.getObject("result", FileSignDTO.class);
                    result.set(fileSignDTO);
                } else {
                    int errCode = jsonObject.getIntValue(PayloadMessage.ERR_CODE);
                    String errMsg = jsonObject.getString(PayloadMessage.ERR_MSG);
                    Logger.e("ApiService", "ERR_CODE->" + errCode + ",ERR_MSG->" + errMsg);
                }
                downLatch.countDown();
            }

            @Override
            public void onFailure(ARequest request, Object message, AError error) {
                Logger.i("getFileSign失败：" + error.getMsg());
                downLatch.countDown();
            }
        });
        if (downLatch.getCount() > 0) {
            try {
                downLatch.await(15, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        if (result.get() != null) {
            return ApiService.uploadFile(result.get(), filePath);
        }
        return null;
    }

    @Override
    public void uploadALB(SparseArray<AlbumDTO> fileUrls) {
//        ApiService.uploadALB(fileUrls);
    }

    @Override
    public boolean uploadChallengeRecord(int sportChallengeId, int sportType, String startTime, String endTime, int totalTime, int rewardValue) throws RemoteException {
        final AtomicBoolean result = new AtomicBoolean(false);
        CountDownLatch downLatch = new CountDownLatch(1);
        ApiService.uploadChallengeRecord(sportChallengeId, sportType, startTime, endTime, totalTime, rewardValue, new IPublishListener() {

            @Override
            public void onSuccess(ARequest request, AResponse response) {
                Logger.i("上传运动挑战成功");
                result.set(true);
                downLatch.countDown();
            }

            @Override
            public void onFailure(ARequest request, Object message, AError error) {
                Logger.i("上传运动挑战失败：" + error.getMsg());
                downLatch.countDown();
            }
        });
        if (downLatch.getCount() > 0) {
            try {
                downLatch.await(15, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return result.get();
    }

    @Override
    public boolean uploadQuranChallengeRecord(int quranLearnId, int chapterIndex, String finishTime, int duration, int rewardValue) {
        final AtomicBoolean result = new AtomicBoolean(false);
        CountDownLatch downLatch = new CountDownLatch(1);
        ApiService.uploadQuranChallengeRecord(quranLearnId, chapterIndex, finishTime, duration, rewardValue, new IPublishListener() {

            @Override
            public void onSuccess(ARequest request, AResponse response) {
                Logger.i("上传古兰经挑战成功");
                result.set(true);
                downLatch.countDown();
            }

            @Override
            public void onFailure(ARequest request, Object message, AError error) {
                Logger.i("上传古兰经挑战失败：" + error.getMsg());
                downLatch.countDown();
            }
        });
        if (downLatch.getCount() > 0) {
            try {
                downLatch.await(15, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return result.get();
    }

    @Override
    public boolean uploadChants(List<ChantsCountDTO> chantsCountDTOList) {
        final AtomicBoolean result = new AtomicBoolean(false);
        CountDownLatch downLatch = new CountDownLatch(1);
        ApiService.uploadChants(chantsCountDTOList, new IPublishListener() {

            @Override
            public void onSuccess(ARequest request, AResponse response) {
                Logger.i("上报CCU事件成功");
                result.set(true);
                downLatch.countDown();
            }

            @Override
            public void onFailure(ARequest request, Object message, AError error) {
                Logger.i("上报CCU事件失败：" + error.getMsg());
                downLatch.countDown();
            }
        });
        if (downLatch.getCount() > 0) {
            try {
                downLatch.await(15, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return result.get();
    }

    @Override
    public String uploadFileByFileType(String filePath, int fileType) throws RemoteException {
        //getFileSign
        JSONObject jsonObject = new JSONObject();
        FileSignBody fileSignBody = FileSignBody.Builder.aFileSignBody()
                .setHolderId(DataProvider.getHolderId())
                .setServiceType(1)
                .setFileType(fileType) //13：SOS录音
                .build();
        JSONObject paramsJsonObject = (JSONObject) JSONObject.toJSON(fileSignBody);
        jsonObject.put("method", MqttConstants.ClientRpcMethod.GET_FILE_SIGN);
        jsonObject.put("params", paramsJsonObject);
        final AtomicReference<FileSignDTO> result = new AtomicReference<>(null);
        CountDownLatch downLatch = new CountDownLatch(1);
        MqttServiceDelegate.getFileSign(jsonObject, new IPublishListener() {

            @Override
            public void onSuccess(ARequest request, AResponse response) {
                String data = response.data.toString();
                Logger.i("getFileSign成功->" + data);
                JSONObject jsonObject = JSONObject.parseObject(data);
                if (jsonObject.containsKey("result")) {
                    FileSignDTO fileSignDTO = jsonObject.getObject("result", FileSignDTO.class);
                    result.set(fileSignDTO);
                } else {
                    int errCode = jsonObject.getIntValue(PayloadMessage.ERR_CODE);
                    String errMsg = jsonObject.getString(PayloadMessage.ERR_MSG);
                    Logger.e("ApiService", "ERR_CODE->" + errCode + ",ERR_MSG->" + errMsg);
                }
                downLatch.countDown();
            }

            @Override
            public void onFailure(ARequest request, Object message, AError error) {
                Logger.i("getFileSign失败：" + error.getMsg());
                downLatch.countDown();
            }
        });
        if (downLatch.getCount() > 0) {
            try {
                downLatch.await(15, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        if (result.get() != null) {
            return ApiService.uploadFile(result.get(), filePath);
        }
        return null;
    }

    @Override
    public void submitTaskRecord(String requestId, List<SubmitTaskRecordDTO> list) throws RemoteException {
        JSONObject jsonObject = new JSONObject();
        JSONObject paramsJsonObject = new JSONObject();
        paramsJsonObject.put("requestId", requestId);
        paramsJsonObject.put("holderId", DataProvider.getHolderId());
        JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(list));
        paramsJsonObject.put("details", jsonArray);

        jsonObject.put("method", MqttConstants.ClientRpcMethod.SUBMIT_TASK_RECORD);
        jsonObject.put("params", paramsJsonObject);
        final AtomicReference<ChantsCounterDTO> result = new AtomicReference<>(null);
        CountDownLatch downLatch = new CountDownLatch(1);
        MqttServiceDelegate.getRecommendStories(jsonObject, new IPublishListener() {
            @Override
            public void onSuccess(ARequest request, AResponse response) {
                String data = response.data.toString();
                Logger.i("submitTaskRecord成功->" + data);
                downLatch.countDown();
            }

            @Override
            public void onFailure(ARequest request, Object message, AError error) {
                Logger.i("submitTaskRecord失败：" + error.getMsg());
                downLatch.countDown();
            }
        });

        if (downLatch.getCount() > 0) {
            try {
                downLatch.await(15, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
